package com.xiaoke.service.impl;

import com.github.pagehelper.Page;
import com.github.pagehelper.PageHelper;
import com.xiaoke.entity.Address;
import com.xiaoke.entity.Coupon;
import com.xiaoke.entity.Order;
import com.xiaoke.entity.UserCoupon;
import com.xiaoke.entity.constant.Constant;
import com.xiaoke.mapper.*;
import com.xiaoke.service.OrderService;
import com.xiaoke.utils.AjaxMsg;
import com.xiaoke.utils.SnowflakeIdWorker;
import org.apache.commons.lang.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.math.BigDecimal;
import java.util.*;

@Service
public class OrderServiceImpl implements OrderService {
    @Autowired
    private OrderMapper orderMapper;
    @Autowired
    private OrderGoodsMapper orderGoodsMapper;
    @Autowired
    private CartMapper cartMapper;
    @Autowired
    private AddressMapper addressMapper;
    @Autowired
    private RegionMapper regionMapper;
    @Autowired
    private CouponMapper couponMapper;
    @Autowired
    private UserCouponMapper userCouponMapper;
    @Autowired
    private SnowflakeIdWorker snowflakeIdWorker;

    @Override
    @Transactional(readOnly = false)
    public void cancelOrder(String orderId) {
        Order order = orderMapper.selectByPrimaryKey(orderId);
        order.setOrderStatus(Constant.ORDER_STATUS_CANCEL);
        orderMapper.updateByPrimaryKeySelective(order);
    }

    @Override
    public Map<String,Object> findOrderDetail(String orderId) {
        Map<String, Object> orderDetail= orderMapper.findOrderDetailById(orderId);

        return orderDetail;
    }

    @Override
    public List<Map<String, Object>> findByUser(String userId,Integer pageNum,Integer pageSize) {
        PageHelper.startPage(pageNum,pageSize,true,false,false);
        Page<Map<String,Object>> page = orderMapper.findByUser(userId);
        List<Map<String, Object>> orders = page.getResult();
        orders.forEach(o ->{
            String orderId = (String) o.get("order_id");
            List<String> goodsPic = orderGoodsMapper.findGoodsPicByOrder(orderId);
            o.put("goods",goodsPic);
        });
        return orders;
    }

    @Override
    @Transactional(readOnly = false)
    public AjaxMsg createOrder(String userId, String shopId, String addressId, String couponId) {
        Order order = new Order();
        String id = String.valueOf(snowflakeIdWorker.nextId());
        String orderNum = createOrderNum();

        List<Map<String, Object>> carts = cartMapper.findByChecked(userId, couponId);
        Address address = addressMapper.selectByPrimaryKey(addressId);
        Map<String, Object> map = cartMapper.sumTotalPriceByChecked(userId, shopId);
        BigDecimal freightPrice = (BigDecimal) map.get("freight_price");
        BigDecimal goodsPrice = (BigDecimal) map.get("goods_price");
        if(StringUtils.isNotBlank(couponId)){
            Coupon coupon = couponMapper.selectByPrimaryKey(couponId);
            if(coupon == null)
                return new AjaxMsg(AjaxMsg.FAILURE,"优惠券不存在!");
            if(coupon.getUseEndDate().before(new Date()))
                return new AjaxMsg(AjaxMsg.FAILURE,"优惠券已过期！");
            if( goodsPrice.compareTo(coupon.getMinAmount()) < 0)
                return new AjaxMsg(AjaxMsg.FAILURE,"订单不满足最低金额！");
            if(coupon.getType().equals("01")){
                //现金券
                order.setActualPrice(goodsPrice.add(freightPrice).subtract(coupon.getValue()));
            }
            if(coupon.getType().equals("02")){
                //折扣
                BigDecimal discountPrice = goodsPrice.add(freightPrice).multiply(coupon.getValue());
                if(discountPrice.compareTo(coupon.getMaxMoney()) > 0)
                    order.setActualPrice( goodsPrice.add(freightPrice).subtract(coupon.getMaxMoney()));
                else
                    order.setActualPrice( goodsPrice.add(freightPrice).subtract(discountPrice));
            }
            UserCoupon userCoupon = userCouponMapper.selectByCouponIdAndUserId(couponId,userId);
            userCoupon.setUsedTime(new Date());
            userCoupon.setOrderId(id);
            userCouponMapper.updateByPrimaryKeySelective(userCoupon);

            order.setCouponId(coupon.getId());
            order.setCouponPrice(coupon.getValue());
        }else {
            order.setActualPrice(goodsPrice.add(freightPrice));
        }
        order.setId(id);
        order.setOrderSn(orderNum);
        order.setOrderStatus("00");
        order.setConsignee(address.getName());
        order.setProvince(regionMapper.selectByPrimaryKey(address.getProvinceId()).getName());
        order.setCity(regionMapper.selectByPrimaryKey(address.getCityId()).getName());
        order.setDistrict(regionMapper.selectByPrimaryKey(address.getDistrictId()).getName());
        order.setAddress(address.getAddress());
        order.setMobile(address.getMobile());
        order.setGoodsPrice(goodsPrice);
        order.setOrderPrice(goodsPrice.add(freightPrice));
        order.setAddTime(new Date());
        order.setFreightPrice(freightPrice.intValue());
        order.setShopId(shopId);

        orderMapper.insert(order);

        return new AjaxMsg();
    }

    @Override
    @Transactional(readOnly = false)
    public String buySuccess(String orderSn, String restMsg) {
        HashMap<String, String> params = new HashMap<String, String>() {
            {
                put("orderSn", orderSn);
            }
        };
        List<Order> orders = orderMapper.findByParams(params);
        Order order = orders.get(0);
        if(order != null && order.getOrderStatus().equals("00")){
            order.setOrderStatus("01");
            orderMapper.updateByPrimaryKeySelective(order);
            return restMsg;
        }
        return null;
    }

    private String createOrderNum() {
        int machineId = 1;//最大支持1-9个集群机器部署
        int hashCodeV = UUID.randomUUID().toString().hashCode();
        if (hashCodeV < 0) {//有可能是负数
            hashCodeV = -hashCodeV;
        }
        //         0 代表前面补充0
        //         4 代表长度为4
        //         d 代表参数为正数型
        return machineId + String.format("%015d", hashCodeV);
    }
}
